/**
 *  Representacion de una empresa
 * 
 * @author Alex Muñoz , Mauricio Orellana
 * @version 2012.05.23
 */
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

public class EmpresaDeServicios 
{
    private HashMap<Contrato,Boolean> contratos;
    private HashMap<Empleado, Boolean> empleados;
    private Menu menu;
    private Lector lector;
    private Formulario formulario;
    
    private static int tasaFijaHH;
    private static int tasaFijaGuardia; 

    /**
     * Constructor de Objetos de la Clase EmpresaDeServicios
     */    
    public EmpresaDeServicios()
    {
        this.contratos = new HashMap();
        this.empleados = new HashMap();
        this.menu = new Menu();
        this.lector = new Lector();
        this.formulario = new Formulario();
    }

    /**
     * Agrega un contrato a la coleccion de contratos
     * 
     * @param contrato El contrato a agregar a la coleccion de contratos
     * @return true si el contrato fue agregado, false si el contrato ya existe
     */
    public boolean addContrato (Contrato contrato)
    {
	if(this.contratos.containsKey(contrato))
        {
            return false;
        }
        return this.contratos.put(contrato,Boolean.TRUE);
    }
    
    /**
     * Eliminar un Contrato de la colección de Contratos
     * 
     * @param contrato Objeto de tipo Contrato que se desea eliminar
     * @return true si el Contrato fue eliminaro, false si el contrato no se pudo eliminar
     */
    public boolean removerContrato(Contrato contrato)
    {
        if(this.contratos.containsKey(contrato))
        {
            if(this.contratos.get(contrato))
            {
                this.terminarContrato(contrato);
            }
            return this.contratos.remove(contrato);
        }
        return false;
    }
    
    /**
     * Terminar Contrato
     * 
     * @param contrato Contrato a finalizar, los empleados estaran disponibles para otros contratos
     */
    public void terminarContrato (Contrato contrato)
    {
	if(this.contratos.containsKey(contrato) & this.contratos.get(contrato) == true)
        {
            this.contratos.put(contrato, Boolean.FALSE);
            this.empleados.put(contrato.getSupervisor(), Boolean.FALSE);
            ArrayList<Empleado> e = contrato.getPlan().getEmpleados();
            for(Empleado emp: e)
            {
               this.empleados.put(emp,Boolean.FALSE);
            }
        }
    }

    /**
     * Obtener un Contrato de la Colección de Contratos
     * 
     * @param rut Cadena que contiene el nombre del Cliente de un Contrato
     * @return Contrato que tiene como nombre de Cliente a la cadea pasada como parametro
     */
    public Contrato getContrato (String rut)
    {
        Iterator<Contrato> it = this.contratos.keySet().iterator();
        
	while(it.hasNext())
        {
            Contrato c = it.next();
            if(c.getRut().equals(rut))
            {
                return c;
            }
        }
        return null;
    }
    
    /**
     * Imprime todos los contratos que se encuentran vigentes
     */
    public void imprimirContratosVigentes()
    {
        Iterator<Contrato> it = this.contratos.keySet().iterator();
        System.out.println("Contratos Vigentes");
        while(it.hasNext())
        {
            Contrato contrato = it.next();
            if(this.contratos.get(contrato))
            {
                contrato.imprimir();
            }
        }
    }
    
    /**
     *  Agrega un Empleado al HashMap de Empleados 
     * 
     * @param empleado Datos del empleado que se desea Agregar
     * @return true si fue posible agregarlo, flase si no fue posible agregarlo
     */
    public boolean addEmpleado (Empleado empleado)
    {
        if(this.rutDeEmpleado(empleado.getRut()))
        {
            return false;
        }
        this.empleados.put(empleado, false);
        return true;
    }
    
    /**
     * Remover Empleado del HashMap
     * 
     * @param empleado Objeto Empleado a ser eliminado del HashMap
     * @return true si se logro remover al empleado, false no se logro remover al empleado
     */
    public boolean removeEmpleado (Empleado empleado)
    {
	if(this.empleados.containsKey(empleado))
        {
            this.empleados.remove(empleado);
            return true;
        }
        return false;
    }
    
    /**
     * Obtener empleado
     * 
     * @param rut Cadena que contiene el nombre del Empleado a obtener
     * @return Objeto Empleado que pose como atributo nombre la cadena pasada como parametro
     */
    public Empleado getEmpleado (String rut)
    {
        Iterator<Empleado> it  = this.empleados.keySet().iterator();
        
        while(it.hasNext())
        {
            Empleado e = it.next();
            if(e.getRut().equals(rut))
            {
                return e;
            }
            
        }
        
        return null;
    }
    
    /**
     * Busca un rut en la base de datos de empleados
     * 
     * @param rut El rut que se busca
     * @return true si el rut pertenece al de algun empleado, false si el rut no pertenece a un empleado
     */
    public boolean rutDeEmpleado(String rut)
    {
        Iterator<Empleado> it = this.empleados.keySet().iterator();
        
        while (it.hasNext())
        {
            if(it.next().getRut().equals(rut))
            {
                return true;
            }
        }
        
        return false;
    }

    /**
     *  Consultar Empleado permite saber todos los contratos en los 
     *  que ha participado un Empleado
     * 
     * @param empleado Objeto Empleado a ser consultado
     */
    public boolean consultarEmpleado (Empleado empleado)
    {
        boolean encontrado = false;
        Iterator<Contrato> it = this.contratos.keySet().iterator();
        
        while(it.hasNext())
        {
            Contrato c = it.next();
            if(c.getPlan().getEmpleados().contains(empleado) || c.getSupervisor().equals(empleado))
            {
                c.imprimir();
                encontrado = true;
            }
        }
        
        return encontrado;
    }
    
    /**
     * Devuelve una coleccion con los empelados diponibles
     * 
     * @return Un coleccion con los empleados que estan disponibles 
     */
    public ArrayList<Empleado> empleadosDisponibles()
    {
        Iterator<Empleado> it = this.empleados.keySet().iterator();
        ArrayList<Empleado> e = new ArrayList<Empleado>();
        while(it.hasNext())
        {
            Empleado empleado = it.next();
            if(this.empleados.get(empleado) == false)
            {
                e.add(empleado);
            }
        }
        return e;
    }
    
    /**
     * Asigna empleados a un plan
     * 
     * @param plan El plan al que se le desea agregar empleados 
     */
    public void asignarEmpleados(Plan plan)
    {
       if(plan instanceof Seguridad)
       {
           if(plan.getTipo().getTipo().equals("Empresa"))
           {
               
           }
       }
       else
       {
           if(plan.getTipo().getTipo().equals("Empresa"))
           {
               
           }
           else
           {
               
           }
       }
    }
    
    /**
     * Imprime todos los empleados del sistema, y su estado de disponibilidad
     */
    public void imprimirEmpleados()
    {
        Iterator<Empleado> it = this.empleados.keySet().iterator();
        System.out.println("---- Lista Empleados ----\n");
        while(it.hasNext())
        {
            Empleado e = it.next();
            e.imprimir();
            System.out.println("Estado: " + ((empleados.get(e)) ? "Trabajando" : "Libre"));
            System.out.println("");

        }
    }
    
    /**
     * Gestion del menu principal
     */
    public void menuPrincipal()
    {
        int op = 0;
        while(op != 4){
            
            this.menu.mostrarMenuPrincipal();
            op = this.lector.leerOpcion();
            
            switch(op){
                case 1:      // administrar contratos
                    this.menuAdministracionContratos();
                    break;
                    
                case 2:      // administrar planes
                    this.menu.mostrarAdministracionPlanes();
                    break;
                
                case 3:      // administrar personal
                    menuAdministracionPersonal();
                    break;
                    
                case 4:      // salir
                    break;
                    
                default:
                    System.out.println("Opcion Invalida");
                    break;
            }
        }
    }
    
    /**
     * Menu para la administracion de personal
     */
    public void menuAdministracionPersonal()
    {
        int op = 1;
        
        while(op != 7){
            
            this.menu.mostrarAdministracionPersonal();
            op = this.lector.leerOpcion();
            
            switch(op)
            {
                case 1:     // agregar empleado
                    if(this.addEmpleado(this.formulario.nuevoEmpleado()))
                    {
                        System.out.println("Nuevo empleado agregado de forma correcta");
                    } 
                    else
                    {
                        System.out.println("Ya existe un empleado con ese rut");
                    }
                    break;
                    
                case 2:     // modificar empleado
                    System.out.print("Rut: ");
                    String rut = this.lector.leerCadena();
                    
                    if(this.getEmpleado(rut) != null)
                    {
                        this.menuModificarEmpleado(getEmpleado(rut));
                    }
                    else
                    {
                        System.out.println("Rut de empleado no encontrado");
                    }
                    break;
                    
                case 3:     // eliminar empleado
                    System.out.print("Ingrese Rut del empleado a ser Eliminado: ");
                    if(this.removeEmpleado(this.getEmpleado(this.lector.leerCadena())))
                    {
                        System.out.println("El empleado fue eliminado");
                    }
                    else
                    {
                        System.out.println("El empleado no ha sido encontrado");
                    }
                    break;
                    
                case 4:     // consultar informacion
                    Empleado e;
                    System.out.print("Ingrese Rut del empleado a consultar: ");
                    String empleadoInfo = this.lector.leerCadena();
                    if((e = this.getEmpleado(empleadoInfo)) != null)
                    {
                        System.out.println("----Informacion----");
                        e.imprimir();
                    }
                    else
                    {
                        System.out.println("El empleado con el nombre: " + empleadoInfo + ", no ha sido encontrado");
                    }
                    break;
                    
                case 5:     // consultar contratos
                    System.out.print("Historial de Contratos\n"
                            + "Ingrese Rut del empleado a consultar:");
                    String empleadoConsultado = this.lector.leerCadena();
                    if ( !this.consultarEmpleado(this.getEmpleado(empleadoConsultado)))
                    {
                        System.out.println("El empleado no ha sido encontrado");
                    }
                    break;
                    
                case 6:   // imprimir lista de empleados 
                    this.imprimirEmpleados();
                    break;
                    
                case 7:     // salir
                    break;
                    
                default:
                    System.out.println("Opcion invalida");
            }
        }
    }
    
    /**
     * Menu para la modificacion de un empleado
     * 
     * @param empleado El empleado que se desea modificar 
     */
    public void menuModificarEmpleado(Empleado empleado)
    {
        int op = 1;
        
        System.out.println("-----Infomacion actual-----");
        empleado.imprimir();
        
        while(op != 5){
            this.menu.mostrarModificarEmpleado();
            op = this.lector.leerOpcion();
            
            switch(op){
                case 1:    // modificar nombre
                    System.out.print("Nuevo nombre: ");
                    empleado.setNombre(this.lector.leerCadena());
                    System.out.println("----Informacion Modificada-----");
                    empleado.imprimir();
                    break;
                    
                case 2:   // modificar rut
                    System.out.print("Nuevo rut: ");
                    empleado.setRut(this.lector.leerCadena());
                    System.out.println("----Informacion Modificada-----");
                    empleado.imprimir();
                    break;
                    
                case 3:   // modificar direccion
                    System.out.print("Nueva direccion: ");
                    empleado.setDireccion(this.lector.leerCadena());
                    System.out.println("----Informacion Modificada-----");
                    empleado.imprimir();
                    break;
                    
                case 4:   // telefono
                    System.out.print("Nuevo telefono: ");
                    empleado.setTelefono(this.lector.leerCadena());
                    System.out.println("----Informacion Modificada-----");
                    empleado.imprimir();
                    break;
                    
                case 5:   // salir
                    break;
                    
                default:
                    System.out.println("Opcion invalida");
            }
        }
    }
    
    /**
     * Menu para la administracion de contratos
     */
    public void menuAdministracionContratos()
    {
        int op = 0;
        
        while(op!=5)
        {
            this.menu.mostrarAdministracionContratos();
            op = lector.leerOpcion();
            String trash;
            Contrato c;
            switch(op)
            {
                case 1:   // agregar contrato
                    if(this.empleadosDisponibles().size() > 1)
                    {
                        c = this.formulario.nuevoContrato();
                        Empleado e = this.empleadosDisponibles().get(0);
                        empleados.put(e, Boolean.TRUE);
                        c.setSupervisor(e);
                        //Ver tema de Condiciones Plan
                    }
                    else
                    {
                        System.out.println("No se encuentran empleados disponibles");
                    }
                    break;
                    
                case 2:   // modificar contrato
                    System.out.println("Ingrese Nombre del cliente:");
                    trash = lector.leerCadena();
                    if((c = this.getContrato(trash)) != null)
                    {
                    
                    }
                    else
                    {
                        System.out.println("No se encuentra al cliente " + trash);
                    }
                    
                    break;
                    
                case 3:   // eliminar informacion de un contrato
                    System.out.println("Eliminar información de un Contrato");
                    if(this.contratos.size()>0)
                    {
                        System.out.print("Ingrese Nombre del Cliente: ");
                        trash = lector.leerCadena();
                        if((c = this.getContrato(trash)) != null)
                        {
                            System.out.println("El Contrato ha sido eliminado: " + this.removerContrato(c));
                        }
                        else
                        {
                            System.out.println("No existe Contrato con " + trash + " como nombre del cliente");
                        }                      
                    }
                    else
                    {
                        System.out.println("No existen Contratos");
                    }
                    break;
                    
                case 4:    // terminar un contrato
                    if(this.contratos.size()>0)
                    {
                        System.out.println("Terminar Contrato"
                                + "\nIngrese Nombre del Cliente:");
                        trash = this.lector.leerCadena();
                        if((c= this.getContrato(trash)) != null)
                        {
                            this.terminarContrato(c);
                        }
                        else
                        {
                            System.out.println("No existe contrato con " + trash + " como nombre del Cliente");
                        }   
                    }
                    else
                    {
                        System.out.println("No existen Contratos");                    
                    } 
                   break;
                    
                case 5:    // imprimir contratos vigentes
                    this.imprimirContratosVigentes();
                    break;
                    
                case 6:   // salir
                    op = 5;
                    break;
                    
                default:
                    System.out.println("Opción Invalida");
            }               
        }
    }
}
